import { defineAsyncComponent } from 'vue';
import { ElMessage } from 'element-plus';
import { openDialog } from './other';

// 说明：Vite 在生产构建时无法对运行时字符串进行打包，因此必须使用 import.meta.glob
// 这里预注册可能被异步打开的组件（views 与 components 下的所有 .vue 文件）
// 注意：键是以 /src 开头的绝对路径
const REGISTERED_COMPONENTS: Record<string, () => Promise<any>> = {
  ...import.meta.glob('/src/views/**/*.vue'),
  ...import.meta.glob('/src/components/**/*.vue'),
};

// 可选：后端键值到真实路径的映射（若后端返回别名而非文件路径，可在此登记）
const COMPONENT_PATH_MAP: Record<string, string> = {};

function normalizeComponentPath(componentPath: string): string {
  if (!componentPath) return '';

  // 去掉多余空白
  let p = componentPath.trim();

  // 兼容后端返回 '/@/xx'、'@/xx'、'/src/xx'、'src/xx'、'/views/xx'、'views/xx'
  if (p.startsWith('/@/')) p = '/src/' + p.slice(3); // '/@/' → '/src/'
  else if (p.startsWith('@/')) p = '/src/' + p.slice(2); // '@/' → '/src/'
  else if (p.startsWith('/views/')) p = '/src/' + p.slice(1); // '/views/' → '/src/views/'
  else if (p.startsWith('views/')) p = '/src/' + p; // 'views/' → '/src/views/'
  else if (p.startsWith('src/')) p = '/' + p; // 'src/xx' → '/src/xx'
  else if (!p.startsWith('/src/')) {
    // 默认补全到 '/src/' 下
    p = '/src/' + p.replace(/^\//, '');
  }

  // 补全后缀名
  if (!p.endsWith('.vue')) {
    // 尝试 '/index.vue' 与 '.vue'
    const tryIndex = p.endsWith('/') ? `${p}index.vue` : `${p}/index.vue`;
    if (REGISTERED_COMPONENTS[tryIndex]) return tryIndex;
    const tryVue = `${p}.vue`;
    if (REGISTERED_COMPONENTS[tryVue]) return tryVue;
  }

  return p;
}

/**
 * 动态加载组件
 * @param componentPath 组件路径（可以是映射键或完整路径）
 * @returns 异步组件
 */
export function loadDynamicComponent(componentPath: string) {
  try {
    // 1) 优先使用映射表
    const mappedPath = COMPONENT_PATH_MAP[componentPath];
    const rawPath = mappedPath || componentPath;

    // 2) 归一化为 /src 开头路径
    const normalizedPath = normalizeComponentPath(rawPath);

    // 3) 从已注册的组件中查找
    const loader = REGISTERED_COMPONENTS[normalizedPath];

    if (!loader) {
      // 尝试再找一次：若末尾包含双扩展(如 '.vue.vue')或路径大小写问题，做一次宽松匹配
      const looseKey = Object.keys(REGISTERED_COMPONENTS).find(k => k.toLowerCase() === normalizedPath.toLowerCase());
      if (looseKey) {
        return defineAsyncComponent({ loader: REGISTERED_COMPONENTS[looseKey] });
      }

      ElMessage.error(`未找到组件: ${rawPath}`);
      throw new Error(`Component not found for path: ${rawPath} -> ${normalizedPath}`);
    }

    // 4) 返回异步组件
    return defineAsyncComponent({
      loader,
      onError: (error, _retry, fail) => {
        // 生产环境直接失败并提示
        console.error('动态组件加载失败:', error, 'path:', componentPath, 'normalized:', normalizedPath);
        ElMessage.error(`组件加载失败: ${componentPath}`);
        fail();
      }
    });
  } catch (error) {
    ElMessage.error(`组件路径无效: ${componentPath}`);
    throw error;
  }
}

/**
 * 动态打开详情弹窗
 * @param title 弹窗标题
 * @param componentPath 组件路径（后端返回的路径）
 * @param data 传递给组件的数据
 * @param width 弹窗宽度
 * @param refreshFunc 刷新函数
 */
export function openDynamicDetailDialog(
  title: string,
  componentPath: string,
  data: any,
  width: string = '70%',
  refreshFunc?: () => void
) {
  try {
    const DynamicComponent = loadDynamicComponent(componentPath);

    // 直接使用导入的 openDialog 方法
    openDialog(title, DynamicComponent, data, refreshFunc, width);
  } catch (error) {
    ElMessage.error('打开详情页面失败');
    console.error('Dynamic dialog error:', error);
  }
} 